package com.grapefruitchat.client.net;

import org.jgroups.ChannelClosedException;
import org.jgroups.ChannelException;
import org.jgroups.ChannelNotConnectedException;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.ReceiverAdapter;

import com.grapefruitchat.client.GrapefruitChat;

/**
 * The {@link NetworkCommsDelegate} handles network communication using the
 * JGroups library. Each instance of {@link GrapefruitChat} should have a single
 * instance of this class, which it can then delegate all client to client
 * communications to.
 * 
 * @author Michael Gierasimiuk, Innovation Science Pty Ltd.
 */
public class NetworkCommsDelegate extends ReceiverAdapter
{
  private JChannel channel;
  
  private String username;
  private String cluster = "Grapefruit Chat Cluster";
  
  /**
   * Creates a new {@link NetworkCommsDelegate}.
   * 
   * @param aUsername the user's name.
   */
  public NetworkCommsDelegate( String aUsername )
  {
    username = aUsername;
    try
    {
      channel = new JChannel();
      channel.setReceiver( this );
    }
    catch ( ChannelException exception )
    {
      // TODO LOGGING
      exception.printStackTrace();
    }
  }
  
  /**
   * Connects to the default cluster. Once connected, it is possible to send
   * messages using the {@link NetworkCommsDelegate}.
   */
  public void connect()
  {
    try
    {
      channel.connect( cluster );
    }
    catch ( ChannelException exception )
    {
      // TODO LOGGING
      exception.printStackTrace();
    }
  }
  
  /**
   * Disconnects from the default cluster. Once disconnected, it is no longer
   * possible to send messages via the {@link NetworkCommsDelegate}.
   */
  public void disconnect()
  {
    // Call to close disconnects from the channel
    channel.close();
  }
  
  /**
   * Sends a given message to all connected of the {@link NetworkCommsDelegate}
   * running on other machines.
   * 
   * @param message the message to send to all other clients currently connected
   *          to the cluster.
   */
  public void send( String message )
  {
    String messageWithUsername = "[" + username + "] " + message;
    System.out.print( ">> " );
    try
    {
      channel.send( new Message( null, null, messageWithUsername ) );
    }
    catch ( ChannelNotConnectedException ex )
    {
      // TODO LOGGING
      ex.printStackTrace();
    }
    catch ( ChannelClosedException ex )
    {
      // TODO LOGGING
      ex.printStackTrace();
    }
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public void receive( Message message )
  {
    if ( message.getObject() instanceof String )
    {
      String text = (String) message.getObject();
      if ( text.indexOf( username ) != 1 )
      {
        System.out.println( text );
        System.out.print( ">> " );
      }
    }
  }
}
